# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import time
import json
import threading
from threading import Lock, Event
from BaseHTTPServer import BaseHTTPRequestHandler

from django.shortcuts import render
from django.http import JsonResponse, HttpResponse, HttpRequest
import psutil
import paramiko
import redis
from dwebsocket.decorators import accept_websocket, require_websocket

from models import TimeSlotNetFlow, TotalNetFlow
from get_vm import GetVMInfo
# Create your views here.

pool = redis.ConnectionPool(host='10.33.64.99')
r = redis.Redis(connection_pool=pool)


def index(request):
    return render(request, 'zdgz.html')


@accept_websocket
def get_vm(request):
    v = GetVMInfo('10.33.64.125', 'root', '1234567')
    if request.is_websocket():
        off_count0, vm_count0 = 0, 0
        while True:
            try:
                data = v.get_vm_list()
                off_count = data["off_count"]
                vm_count = data["vm_count"]
            except Exception as e:
                print e, "与vCenter断开链接"
                v = GetVMInfo('10.33.64.125', 'root', '1234567')
                data = v.get_vm_list()
                off_count = data["off_count"]
                vm_count = data["vm_count"]
            if off_count != off_count0 or vm_count !=vm_count0:
                data["state"] = 1
                request.websocket.send(json.dumps(data))
                off_count0, vm_count0 = off_count, vm_count
            elif request.websocket.has_messages():
                request.websocket.read()
                request.websocket.send(json.dumps({"state": 0}))
            time.sleep(10)
    else:
        return JsonResponse(v.get_vm_list())


def calc_speed(time_str):
    ft = r.rpop("fw_tx_" + time_str)
    fr = r.rpop("fw_rx_" + time_str)
    sr = r.rpop("sw_rx_" + time_str)
    st = r.rpop("sw_tx_" + time_str)
    return int(ft), int(fr), int(sr), int(st)


def clac_speed2(l):
    result = []
    for i in range(len(l)-1):
        if int(l[i+1]) < int(l[i]):
            result.append(round((4294967296 - int(l[i]) + int(l[i+1]))/1024.0, 2))
        else:
            result.append(round((int(l[i+1]) - int(l[i]))/1024.0, 2))
    return result


@accept_websocket
def net_speed(request):
    clients = []
    time_str = time.strftime("%m%d")
    length = 200
    lock = threading.RLock()
    if request.is_websocket():
        # a = []
        # b = []
        # c = []
        # d = []
        while True:
            if not time_str == time.strftime("%m%d"):
                time_str = time.strftime("%m%d")
            l = r.llen("fw_tx_" + time_str)
            try:
                lock.acquire()
                clients.append(request.websocket)
                # ft = r.lrange("fw_tx_" + time_str, -2, -1)
                # fr = r.lrange("fw_rx_" + time_str, -2, -1)
                # st = r.lrange("sw_tx_" + time_str, -2, -1)
                # sr = r.lrange("sw_rx_" + time_str, -2, -1)
                # a.extend(clac_speed2(ft))
                # b.extend(clac_speed2(fr))
                # c.extend(clac_speed2(sr))
                # d.extend(clac_speed2(st))
                # data = {"speed": {'fw_tx': a, 'fw_rx': b,
                #         'sw_rx': c, 'sw_tx': d}, "max_length": length, "state": 1, "passivity": False}

                # if request.websocket.has_messages():
                #     if request.websocket.read():
                #         request.websocket.send(json.dumps(full_net_speed(time_str, len(a), length)))
                #     else:
                #         request.websocket.close()
                #         break
                # else:
                for client in clients:
                    client.send(json.dumps(full_net_speed(time_str, length)))
            finally:
                clients.remove(request.websocket)
                lock.release()
            while True:
                if l < r.llen("fw_tx_" + time_str):
                    break
            # if len(a) >= length:
            #     a.remove(a[0])
            #     b.remove(b[0])
            #     c.remove(c[0])
            #     d.remove(d[0])
            # while True:
            #     if l < r.llen("fw_tx_" + time_str):
            #         break
    else:
        return JsonResponse(full_net_speed(time_str, length))


def full_net_speed(time_str, length, max_length=100):
    num = 0
    time_str1 = ''
    if not time_str == time.strftime("%m%d"):
        time_str1 = time.strftime("%m%d")
        num = r.llen('fw_tx_' + time_str1)

    ft = r.lrange("fw_tx_" + time_str, -(length+1-num), -1) + r.lrange("fw_tx_" + time_str1, 0, num)
    fr = r.lrange("fw_rx_" + time_str, -(length+1-num), -1) + r.lrange("fw_tx_" + time_str1, 0, num)
    st = r.lrange("sw_tx_" + time_str, -(length+1-num), -1) + r.lrange("fw_tx_" + time_str1, 0, num)
    sr = r.lrange("sw_rx_" + time_str, -(length+1-num), -1) + r.lrange("fw_tx_" + time_str1, 0, num)
    # print len(ft), ft
    d = {'fw_tx': clac_speed2(ft), 'fw_rx': clac_speed2(fr), 'sw_rx': clac_speed2(sr), 'sw_tx': clac_speed2(st)}
    data = {"speed": d, "max_length": length, "state": 1, 'passivity': True}
    return data


def sys_info(request):
    data = {}
    data["cpu_percent"] = psutil.cpu_percent()
    data["mem_percent"] = psutil.virtual_memory().percent
    if psutil.WINDOWS:
        data["disk_percent"] = psutil.disk_usage('C:').percent
    else:
        data["disk_percent"] = psutil.disk_usage('/').percent
    ssh = SysSSHClient(hostname='10.33.64.99', username='root', password='Vdin1234', port=22)
    oids = ['ifInOctets.777', 'ifOutOctets.777', 'ifInOctets.1025', 'ifOutOctets.1025']
    cmd = ''
    for oid in oids:
        cmd += 'snmpwalk -v 2c -c Vdin1234 1.1.1.1 %s && ' % oid
    result = ssh.run_command(cmd.strip('&& ')).readlines()
    data["fw_rx"] = long(result[0].strip().split()[-1])
    data["fw_tx"] = long(result[1].strip().split()[-1])
    data["sw_rx"] = long(result[2].strip().split()[-1])
    data["sw_tx"] = long(result[3].strip().split()[-1])
    ssh.close()
    return JsonResponse(data)


@accept_websocket
def flow(request):
    if request.is_websocket():
        clients = []
        lock = threading.RLock()
        data = {}
        id = 0
        while True:
            interval = TimeSlotNetFlow.objects.all().order_by('-id')[:7]
            hour_interval_flow = []
            for i in range(len(interval)):
                hour_interval_flow.append({"fw_tx": interval[i].firewall_tx, "fw_rx": interval[i].firewall_rx,
                                           "sw_tx": interval[i].switch_tx, "sw_rx": interval[i].switch_rx,
                                           "hour": interval[i].end_time.hour,
                                           "time": interval[i].end_time.strftime("%H:%M")})
            data["hour_interval_flow"] = hour_interval_flow
            data["state"] = 1
            try:
                lock.acquire()
                clients.append(request.websocket)
                for client in clients:
                    if not client.has_messages():
                        if id != interval[0].id:
                            client.send(json.dumps(data))
                            id = interval[0].id
                    else:
                        client.read()
                        client.send(json.dumps({"state": 0}))
            finally:
                clients.remove(request.websocket)
                lock.release()
            time.sleep(10)

    else:
        data = {}
        total = TotalNetFlow.objects.order_by('-id').first()
        data["total"] = {"fw_rx": total.firewall_rx_total, "fw_tx": total.firewall_tx_total,
                         "sw_rx": total.switch_rx_total, "sw_tx": total.switch_tx_total, "time": total.add_time}
        interval = TimeSlotNetFlow.objects.all().order_by('-id')[:7]
        print total, interval
        hour_interval_flow = []
        for i in range(len(interval)):
            # data[str(interval[i].end_time.hour) + ":"+str(interval[i].end_time.minute) +
            #      ":"+str(interval[i].end_time.second)] = {"fw_tx": interval[i].firewall_tx, "fw_rx": interval[i].firewall_rx,
            #                                                 "sw_tx": interval[i].switch_tx, "sw_rx": interval[i].switch_rx}
            hour_interval_flow.append({"fw_tx": interval[i].firewall_tx, "fw_rx": interval[i].firewall_rx,
                                      "sw_tx": interval[i].switch_tx, "sw_rx": interval[i].switch_rx,
                                       "hour": interval[i].end_time.hour, "time": interval[i].end_time.strftime("%H:%M")})
        data["hour_interval_flow"] = hour_interval_flow
        print data
        return JsonResponse(data)


@require_websocket
def test(request):
    lock = threading.RLock()
    time_str = time.strftime("%m%d")
    global speed
    speed = {}
    length = 100
    keys = ["fw_tx", "fw_rx", "sw_rx", "sw_tx"]
    while True:
        if not time_str == time.strftime("%m%d"):
            time_str = time.strftime("%m%d")
        time.sleep(0.8)
        try:
            lock.acquire()
            clients.append(request.websocket)
            # for message in request.websocket:
            #     if not message:
            #         break
            for key in keys:
                speed[key] = get_speed(key+'_'+time_str)
            for client in clients:
                client.send(json.dumps(speed))
        finally:
            clients.remove(request.websocket)
            lock.release()
    # time_str = time.strftime("%m%d")
    # length = 100
    # global speed
    # speed = {}
    # while True:
    #     if not time_str == time.strftime("%m%d"):
    #         time_str = time.strftime("%m%d")
    #     keys = ["fw_tx", "fw_rx", "sw_rx", "sw_tx"]
    #     for key in keys:
    #         speed[key] = get_speed(key+'_'+time_str)
    #     print speed
    #     request.websocket.send(json.dumps(speed))
    #     time.sleep(2)


def get_speed(key):
    l = r.lrange(key, -2, -1)
    result = []
    for i in range(len(l)-1):
        if int(l[i+1]) < int(l[i]):
            result.append(round((4294967296 - int(l[i]) + int(l[i+1]))/1024.0, 2))
        else:
            result.append(round((int(l[i+1]) - int(l[i]))/1024.0, 2))
    if speed.get(key):
        speed[key] += result
    else:
        speed[key] = result
    return speed[key]


class SysSSHClient(object):
    def __init__(self, hostname, username, password, port=22, keepalive=None):
        self.hostname = hostname
        self.username = username
        self.password = password
        self.port = port
        self.keepalive = keepalive
        self.connected = Event()
        self.lock = Lock()
        self.ssh = paramiko.SSHClient()
        self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

    def _do_connect(self):
        self.ssh.connect(hostname=self.hostname, username=self.username, password=self.password, port=self.port)

    def _connect(self):
        """ Connect to the remote if not already connected. """
        if not self.connected.is_set():
            try:
                self.lock.acquire()
                # Another thread may have connected while we were
                # waiting to acquire the lock
                if not self.connected.is_set():
                    self._do_connect()
                    self.connected.set()
            except :
                raise
            finally:
                self.lock.release()

    def run_command(self, command):
        self._connect()
        stdin, stdout, stderr = self.ssh.exec_command(command)
        return stdout

    def close(self):
        self.ssh.close()


if __name__ == "__main__":
    a = SysSSHClient(hostname='10.33.64.99', username='root', password='Vdin1234', port=22)
    result = a.run_command("top -b -n 2|sed '/^[0-9 ]/'d |sed '/^$/d'").readlines()[-5:]
    result = a.run_command("df -h").readlines()
    print result
